<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace app\api\service\order;

use app\api\model\Goods as GoodsModel;
use app\common\enum\order\DeliveryStatus as DeliveryStatusEnum;
use app\common\library\helper;
use app\common\model\OrderSub as OrderSubModel;
use think\facade\Event;
use app\common\service\BaseService;
use app\api\model\User as UserModel;
use app\api\model\Order as OrderModel;
use app\api\model\OrderGoods as OrderGoodsModel;
use app\api\model\user\BalanceLog as BalanceLogModel;
use app\common\service\goods\source\Factory as StockFactory;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\order\PayStatus as PayStatusEnum;
use app\common\enum\order\PayType as OrderPayTypeEnum;
use app\common\enum\user\balanceLog\Scene as SceneEnum;
use app\common\enum\order\OrderStatus as OrderStatusEnum;

/**
 * 订单支付成功服务类
 * Class PaySuccess
 * @package app\api\service\order
 */
class PaySuccess extends BaseService
{
    // 订单模型
    public $model;
    public $subModel;

    // 当前用户信息
    private $user;

    /**
     * 构造函数
     * PaySuccess constructor.
     * @param $orderNo
     */
    public function __construct($orderNo)
    {
        parent::__construct();
        // 实例化订单模型
        $this->model    = OrderModel::getPayDetail($orderNo);
        $this->subModel = OrderSubModel::getOrderSubDetail($orderNo, 10);
        // 获取用户信息
        $this->user = UserModel::detail($this->model['user_id']);
    }

    /**
     * 获取订单详情
     * @return OrderModel|null
     */
    public function getOrderInfo()
    {
        $this->model['good_type'] = '';
        if ($order_goods = $this->model['goods']) {
            foreach ($order_goods as $item) {
                $this->model['good_type'] = $item['goods']['good_type'];
            }
        }
        return $this->model;
    }

    /**
     * 订单支付成功业务处理
     * @param $payType
     * @param array $payData
     * @return bool
     */
    public function onPaySuccess($payType, $payData = [])
    {
        if (empty($this->model)) {
            $this->error = '未找到该订单信息';
            return false;
        }
        // 更新付款状态
        $status = $this->updatePayStatus($payType, $payData);
        // 订单支付成功事件
        if ($status == true) {
            Event::trigger('OrderPaySuccess', ['order' => $this->model, 'orderType' => OrderTypeEnum::ORDER]);
        }
        return $status;
    }

    /**
     * 更新付款状态
     * @param $payType
     * @param array $payData
     * @return bool
     */
    private function updatePayStatus($payType, $payData = [])
    {
        // 验证余额支付时用户余额是否满足
        if ($this->subModel['bd_type'] == OrderPayTypeEnum::BALANCE) {
            if ($this->user['balance'] < $this->subModel['deduction_value']) {
                $this->error = '用户余额不足，无法使用余额支付';
                return false;
            }
        }

        // 事务处理
        $this->model->transaction(function () use ($payType, $payData) {
            //用户支付成功按供应商拆订单
            $this->splitOrderBySupplier($payType, $payData);
            // 更新订单状态
            $this->updateOrderInfo($payType, $payData);
            // 更新子订单状态
            $this->updateOrderSubInfo($payType,$payData);
            // 累积用户总消费金额
            UserModel::setIncPayMoney($this->user['user_id'], (float)$this->model['pay_price']);
            // 记录订单支付信息
            $this->updatePayInfo();
        });
        return true;
    }

    /**
     * 更新订单记录
     * @param int $payType
     * @param array $payData
     * @return false|int
     * @throws \Exception
     */
    private function updateOrderInfo(int $payType, array $payData)
    {
        // 更新商品库存、销量
        StockFactory::getFactory($this->model['order_source'])->updateStockSales($this->model['goods']);
        // 整理订单信息
        $order = [
            'pay_type'   => $payType,
            'pay_status' => PayStatusEnum::SUCCESS,
            'pay_time'   => time()
        ];
        if ($payType == OrderPayTypeEnum::WECHAT) {
            $order['transaction_id'] = $payData['transaction_id'];
        }
        if (isset($payData['good_type']) && $payData['good_type'] == 'virtual_good') {//购买虚拟商品发货状态  已发货
            $order['delivery_status'] = DeliveryStatusEnum::DELIVERED;
            $order['delivery_time'] = time();
        }
        if(isset($payData['order_id'])){//更新子订单
            $this->model::update($order,['order_parent_id'=>$payData['order_id']]);
        }
        // 更新订单状态
        return $this->model->save($order);
    }

    /**
     * 更新子订单记录
     * @return false|int
     * @throws \Exception
     */
    private function updateOrderSubInfo($payType,$payData)
    {
        // 整理订单信息
        $order = [
            'pay_type'         =>$payType,
            'state'            => PayStatusEnum::SUCCESS,
            'tmp_out_tarde_no' => $payData['tmpOutTardeNo'] ?? '',//微信临时支付单号
            'pay_time'         => time()
        ];
        // 更新订单状态
        return $this->subModel->save($order);
    }

    /**
     * 记录订单支付信息
     */
    private function updatePayInfo()
    {
        if ($this->subModel['bd_type'] == OrderPayTypeEnum::BALANCE) {//余额支付更新用户余额
            UserModel::setDecBalance((int)$this->user['user_id'], (float)$this->subModel['deduction_value']);
        }
        // 新增余额变动记录
        BalanceLogModel::add(SceneEnum::CONSUME, [
            'user_id'         => (int)$this->user['user_id'],
            'money'           => -$this->subModel['pay_money'],
            'correlation_id'  => $this->subModel['order_id'],
            'bd_type'         => $this->subModel['bd_type'],
            'deduction_value' => -$this->subModel['deduction_value'],
        ], ['order_no' => $this->model['order_no']]);

        // 余额支付
        /*if ($payType == OrderPayTypeEnum::BALANCE) {
            // 更新用户余额
            UserModel::setDecBalance((int)$this->user['user_id'], (float)$this->model['pay_price']);
            // 新增余额变动记录
            BalanceLogModel::add(SceneEnum::CONSUME, [
                'user_id' => (int)$this->user['user_id'],
                'money' => -$this->model['pay_price'],
            ], ['order_no' => $this->model['order_no']]);
        }
        // 微信支付
        if ($payType == OrderPayTypeEnum::WECHAT) {

        }*/
    }

    /**
     * 按供应商拆分订单
     * @param int $payType
     * @param $payData
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function splitOrderBySupplier(int $payType, $payData)
    {
        $result = [];
        foreach ($this->model['goods'] as $value) {
            $key = $value['supplier_id']; // 将子数组转换为字符串作为新数组的键
            if (array_key_exists($key, $result)) {
                // 如果键已存在，则将值相加
                $result[$key]['total_price']     = helper::bcadd($result[$key]['total_price'], $value['total_price']);
                $result[$key]['total_pay_price'] = helper::bcadd($result[$key]['total_pay_price'], $value['total_pay_price']);
                $result[$key]['coupon_money']    = helper::bcadd($result[$key]['coupon_money'], $value['coupon_money']);
            } else {
                // 如果键不存在，则直接添加到新数组
                $result[$key]['total_price']     = $value['total_price'];
                $result[$key]['total_pay_price'] = $value['total_pay_price'];
                $result[$key]['coupon_money']    = $value['coupon_money'];
            }
        }
        $orderModel      = new OrderModel;
        $OrderGoodsModel = new OrderGoodsModel;
        $i               = 0;
        foreach ($result as $key => $value) {
            //该供应商订单使用优惠券金额
            $order_price    = helper::bcsub($value['total_price'], $value['coupon_money']);
            $transaction_id = '';
            if ($payType == OrderPayTypeEnum::WECHAT) {
                $transaction_id = $payData['transaction_id'];
            }
            $i++;
            // 订单数据
            $data[] = [
                'user_id'         => $this->user['user_id'],
                'order_parent_id' => $this->model['order_id'],
                'order_no'        => $this->model['order_no'] . '_' . $i,
                'total_price'     => $value['total_price'],
                'order_price'     => $order_price,
                'coupon_id'       => $this->model['coupon_id'],
                'coupon_money'    => $value['coupon_money'],
                //'points_money' => $isExistPointsDeduction ? $order['pointsMoney'] : 0.00,积分暂时不用
                //'points_num' => $isExistPointsDeduction ? $order['pointsNum'] : 0,积分暂时不用
                'pay_price'       => $value['total_pay_price'],
                'pay_status'      => PayStatusEnum::SUCCESS,
                'pay_time'        => time(),
                'delivery_type'   => $this->model['delivery_type'],
                'order_source'    => $this->model['order_source'],
                'order_source_id' => $this->model['order_source_id'],
                'platform'        => $this->model['platform'],
                //'points_bonus' => $order['pointsBonus'],暂时没有积分赠送
                'order_status'    => OrderStatusEnum::NORMAL,
                'supplier_id'     => $key,
                'transaction_id'  => $transaction_id,
                'store_id'        => $this->storeId,
            ];
        }

        if (count($data) > 1) { //生成了子订单，删除父订单
            $orderModel->updateBase(['is_delete' => 1], ['order_id' => $this->model['order_id']]);
        } else { //该订单只有一个供应商
            $orderModel->updateBase(['order_parent_id' => $this->model['order_id'], 'supplier_id' => $data[0]['supplier_id']], ['order_id' => $this->model['order_id']]);
            return $OrderGoodsModel->updateBase(['order_parent_id' => $this->model['order_id']], ['order_id' => $this->model['order_id']]);
        }
        //按供应商分单写入数据库
        $orderModel->saveAll($data);
        if ($data) {//生成子订单id写入订单商品表
            foreach ($data as $value) {
                $info = $orderModel->where('order_parent_id', '=', $value['order_parent_id'])
                    ->where('supplier_id', '=', $value['supplier_id'])
                    ->find();
                if ($info['order_id']) {
                    $where = [['order_id', '=', $value['order_parent_id']], ['supplier_id', '=', $value['supplier_id']]];
                    // 更新记录
                    $OrderGoodsModel->updateBase(['order_id' => $info['order_id'], 'order_parent_id' => $value['order_parent_id']], $where);
                }

            }
        }
    }

}